const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
function MyPromise(executor) {
	this.status = PENDING;
	this.onFulFilleds = [];
	this.onRejecteds = [];
	this.result = null;
	function resolve(v) {
		if (this.status === PENDING) {
			this.status = FULFILLED;
			this.result = v;
			resolvePromise(this);
		}
	}
	function reject(reason) {
		if (this.status === PENDING) {
			this.status = REJECTED;
			this.result = reason;
			rejectPromise(this);
		} 
	}
	executor(resolve.bind(this), reject.bind(this));
}

function resolvePromise(myPromise) {
	queueMicrotask(() => {
		for (const [callback, resolve, reject] of myPromise.onFulFilleds) {
			try {
				const x = callback(myPromise.result);
				if (x instanceof MyPromise) {
					x.then(res => {
						resolve(res);
					})
				} else {
					resolve(x);
				}
			} catch (e) {
				reject(e);
			}
		}
		myPromise.onFulFilleds.length = 0;
	})
}

function rejectPromise(myPromise) {
	queueMicrotask(() => {
		for (const [callback, resolve, reject] of myPromise.onRejecteds) {
			callback(myPromise.result);
		}
		myPromise.onRejecteds.length = 0;
	})
}

MyPromise.prototype.then = function (onFulFilled = v => v, onRejected = reason => { throw reason}) {
    return new MyPromise((resolve, reject) => {
      this.onFulFilleds.push([onFulFilled, resolve, reject]);
      this.onRejecteds.push([onRejected, resolve, reject]);
      if (this.status === FULFILLED) {
        resolvePromise(this);
      } else if (this.status === REJECTED) {
        rejectPromise(this);
      }
    });
  }

MyPromise.all = function(promises) {
	return new MyPromise((resolve, reject) => {
		let resolveCount = 0;
		const results = [];
		
		for (const [i, p] of promises.entries()) {
			p.then(r => {
				results[i] = r;
				resolveCount++;
				if (resolveCount === promises.length) {
					resolve(results);
				}
			}, e => {
				reject(e);
			})
		}
	})
}

MyPromise.race = function (promises) {
    return new MyPromise((resolve, reject) => {
      for (const p of promises) {
        p.then((r) => {
          resolve(r);
        }, (e) => {
          reject(e);
        });
      }
    });
  }

// export default MyPromise;

// let p = new MyPromise((resolve,reject) => {
//     setTimeout(()=>{
//         resolve(1)
//     },3000)
// })
// p.then((res)=>{console.log(res)}).then(()=>{console.log(2)}).then(()=>{console.log(3)})
let p2 = new MyPromise((resolve,reject) => {
	setTimeout(()=>{
		resolve('a')
	},3000)
})
p2.then((res)=>{
	console.log(res)
	return new MyPromise((resolve,reject) => {
		setTimeout(()=>{
			resolve('b')
		},2000)
	})
}).then((v)=>{console.log(v)}).then(()=>{console.log('结束')})
